'use strict';
const { program } = require('commander');
const { spawnSync } = require('child_process');
const ControllerTemplate = require('./template/controller');
const RouterTemplate = require('./template/router');
const ConfigTemplate = require('./template/config');
const PackageTemplate = require('./template/package');
const DB = require('./db');
const util = require('./util');
const fs = require('fs');
const path = require('path');

async function main() {
  program
    .option('-H, --host <localhost>', 'mysql host')
    .option('-p, --port <port>', 'mysql port', 3306)
    .option('-d, --db-name <name>', 'mysql db name')
    .option('-u, --user <user>', 'mysql user')
    .option('-P, --pwd <pwd>', 'mysql password')
    .option(', --path <path>', 'generator file path', './server');

  program.parse(process.argv);

  const options = program.opts();
  if (!assertParams(options)) {
    return;
  }
  var db = new DB({
    host: options.host,
    port: options.port,
    password: options.pwd,
    user: options.user,
    database: options.dbName
  });
  await db.init();
  await generateApi(options, db);
  await generateMd(options, db);
  process.exit();
}

function assertParams(options) {
  var assertResult = true;
  if (!options.host) {
    console.log('db host must provide');
    assertResult = false;
  }
  if (!options.port) {
    console.log('db port must provide');
    assertResult = false;
  }
  if (!options.dbName) {
    console.log('db name must provide');
    rassertResult = false;
  }
  if (!options.user) {
    console.log('db user must provide');
    assertResult = false;
  }
  if (!options.pwd) {
    console.log('db password must provide');
    assertResult = false;
  }
  return assertResult;
}

async function generateApi(options, db) {
  var generatePath = path.join(process.cwd(), options.path);
  var tables = await db.getTables(options.dbName);

  //生成controller
  var controllerPath = generatePath + '/controller';
  util.createFolder(controllerPath);
  for (let i = 0; i < tables.length; i++) {
    var fields = await db.getFields(tables[i].name);
    var fieldNames = [];
    fields.forEach((field) => fieldNames.push(field.name));
    var text = new ControllerTemplate(
      tables[i].name,
      fieldNames
    ).generateFile();
    fs.writeFileSync(`${controllerPath}/${tables[i].name}.js`, text);
  }

  //生成router
  var routerPath = generatePath + '/router';
  util.createFolder(routerPath);
  var tableNames = [];
  tables.forEach((table) => tableNames.push(table.name));
  var text = new RouterTemplate(tableNames).generateFile();
  fs.writeFileSync(`${routerPath}/index.js`, text);

  //生成config
  var configPath = generatePath + '/configs';
  util.createFolder(configPath);
  var text = new ConfigTemplate(options).generateFile();
  fs.writeFileSync(`${configPath}/index.js`, text);

  //生成api_test.json
  var text = new PackageTemplate(options).generateEnv();
  fs.writeFileSync(`${generatePath}/api_test.json`, text);

  //生成.gitignore
  var text = new PackageTemplate(options).generateGitignore();
  fs.writeFileSync(`${generatePath}/.gitignore`, text);

  //生成.prettierrc
  var text = new PackageTemplate(options).generatePrettierrc();
  fs.writeFileSync(`${generatePath}/.prettierrc.js`, text);

  //生成models
  var modelPath = generatePath + '/models';
  util.createFolder(modelPath);
  spawnSync('./node_modules/sequelize-auto/bin/sequelize-auto', [
    '-o',
    modelPath,
    '-d',
    options.dbName,
    '-h',
    options.host,
    '-u',
    options.user,
    '-p',
    options.port,
    '-x',
    options.pwd,
    '-e',
    'mysql',
    '-v',
    true
  ]);
  if (options.path != './server') {
    spawnSync('cp', ['-r', 'server/util', generatePath]);
    spawnSync('cp', ['server/package.json', generatePath]);
    spawnSync('cp', ['server/server.js', generatePath]);
  }
  //格式化代码
  spawnSync('npx', ['prettier', '--write', generatePath]);
}

async function generateMd(options, db) {
  var text = `#数据库设计\n`;
  var tables = await db.getTables();
  for (let i = 0; i < tables.length; i++) {
    var fields = await db.getFields(tables[i].name);
    text += `## ${tables[i].name}: ${tables[i].comment}\n`;
    text += `|  | 数据类型 | 注释 |\n`;
    text += `| :--- | :--- | :--- |\n`;
    for (let j = 0; j < fields.length; j++) {
      text += `| ${fields[j].name} | ${fields[j].type} | ${fields[j].comment} |\n`;
    }
    text += `\n`;
  }
  var generatePath = path.join(process.cwd(), options.path);
  //生成数据库设计文档
  var docPath = generatePath + '/doc';
  util.createFolder(docPath);
  fs.writeFileSync(`${docPath}/db.md`, text);
}

main();
